
""" 处理 excel 数据，推送数据给扫描脚本并返回扫描结果。"""

import os
import json
import pandas as pd
import logging
import requests
import pprint
from requests.exceptions import RequestException
from project.colored_logging import configure_logging
# 定义常量

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
DICT_DIR = os.path.join(BASE_DIR, "dict")
JSON_FILE_PATH = os.path.join(DICT_DIR, "data.json")

custom_keyword_colors = {
    'error': 'RED',
    'warning': 'YELLOW',
    'critical': 'MAGENTA',
    'successfully': 'GREEN'
}

logger = configure_logging(keywords=['error', 'warning', 'critical', 'successfully'],
                        keyword_colors=custom_keyword_colors)

def convert_excel_to_json(excel_file):
    """
    从 Excel 文件中读取数据并转换为 JSON 格式。
    :param excel_file: Excel 文件路径
    :return: 转换后的 JSON 数据
    """
    # 定义变量列表
    ip_variable = ['IP', 'iP', 'Ip', 'ip']
    port_variable = ['端口', 'Ports', 'port', 'ports']
    try:
        logging.info("准备读取 Excel 文件。")
        # 自定义函数用于转换 ip 和端口列的值
        def convert_value(value, variable_list):
            if isinstance(value, str) and any(item in value for item in variable_list):
                return variable_list[0]
            else:
                return value

        def convert_ip(x):
            return convert_value(x, ip_variable)

        def convert_port(x):
            return convert_value(x, port_variable)

        # 读取 Excel 文件并进行转换
        df = pd.read_excel(excel_file, converters={'ip': convert_ip, '端口': convert_port}).astype(str)
        df.fillna('', inplace=True)
        logging.info("成功读取 Excel 文件。")

    except Exception as e:
        logging.error(f"无法读取 Excel 文件：{e}")
        raise ValueError(f"无法读取 Excel 文件：{e}")

    # 检查是否存在类似 'ip' 的字段
    ip_field_found = any(field in df.columns for field in ip_variable)
    if not ip_field_found:
        logging.error("Excel 文件中未找到类似 'ip' 的列。")
        raise KeyError("Excel 文件中必须包含类似 'ip' 的列。")

    data = []
    for _, row in df.iterrows():
        # 通过变量列表匹配 'ip' 字段的值
        for field in df.columns:
            if any(item in field for item in ip_variable):
                ip = row[field]
                break
        # 通过变量列表匹配 '端口' 字段的值
        for field in df.columns:
            if any(item in field for item in port_variable):
                ports = row[field]
                break
        if pd.notna(ip) and pd.notna(ports):
            port_list = str(ports).split(',') if isinstance(ports, str) else []
            for port in port_list:
                if not port or port.strip() == '' or port.strip() == 'nan':
                    port = 'None'
                data.append({"ip": ip, "port": str(port)})
    logging.info(f"成功解析 Excel 文件。")
    
    # 检查 Dict 目录是否存在
    if not os.path.exists(DICT_DIR):
        try:
            os.makedirs(DICT_DIR)
            logging.info("成功创建 dict 目录。")
            # 创建 Dict 目录后，直接创建 data.json 文件
            with open(JSON_FILE_PATH, 'w') as f:
                pass
            logging.info("成功创建 data.json 文件。")
        except OSError as e:
            logging.error(f"创建 dict 目录及 data.json 文件时出错: {e}")
            return
    else:
        # Dict 目录存在，检查 data.json 文件是否存在
        if not os.path.exists(JSON_FILE_PATH):
            try:
                with open(JSON_FILE_PATH, 'w') as f:
                    pass
                logging.info("成功创建 data.json 文件。")
            except OSError as e:
                logging.error(f"创建 data.json 文件时出错: {e}")
                return
    # 写入 JSON 数据
    try:
        with open(JSON_FILE_PATH, 'w') as json_file:
            json_file.write(json.dumps(data, indent=4))
        logging.info("成功写入 Json 文件。")
    except OSError as e:
        logging.error(f"写入 Json 文件时出错: {e}")


def start_scan():
    """
    从 JSON 文件中读取数据并发送到 Flask 服务器。
    发起扫描请求。
    """
    # 读取 JSON 数据
    try:
        with open(JSON_FILE_PATH, 'r') as f:
            try:    
                data = json.load(f)
                logging.info(f"成功拉取 Json 数据。")
            except json.JSONDecodeError:
                logging.error("无法解析 json 文件。请检查文件或内容是否正确。")
                return

        # 发送数据到 Flask 服务器
        logging.info(f"准备推送 Json 数据。")
        # pprint.pprint(data)

        for _ in range(3):  # 重试 3 次
            try:
                logging.info(f"成功推送 Json 数据。")
                logging.info(f"正在发起扫描请求。")
                response = requests.post('http://127.0.0.1:5001/scan', json=data)
                if response.status_code == 200:
                    return
                else:
                    logging.error(f"请求失败，状态码：{response.status_code}。响应内容：{response.text}。正在尝试重试...")
            except RequestException as e:
                logging.error(f"请求错误：{e}。正在尝试重试...")
        logging.error("多次尝试后请求仍然失败。")
    except FileNotFoundError:
        logging.error("data.json文件不存在。请检查文件路径是否正确。")
    except RequestException as e:
        logging.error(f"请求错误：{e}")
